#ifndef SEMINIX_SCHED_TASK_STACK_H
#define SEMINIX_SCHED_TASK_STACK_H

#include <seminix/sched.h>
#include <ulinux/linux/magic.h>

/*
 * When accessing the stack of a non-current task that might exit, use
 * try_get_task_stack() instead.  task_stack_page will return a pointer
 * that could get freed out from under you.
 */
static inline void *task_stack_page(const struct task_struct *task)
{
    return task->stack;
}

#define setup_thread_stack(new,old)	do { } while(0)

static inline unsigned long *end_of_stack(const struct task_struct *task)
{
    return task->stack;
}

static inline void *try_get_task_stack(struct task_struct *tsk)
{
    return atomic_inc_not_zero(&tsk->stack_refcount) ?
        task_stack_page(tsk) : NULL;
}

extern void put_task_stack(struct task_struct *tsk);

#define task_stack_end_corrupted(task) \
        (*(end_of_stack(task)) != STACK_END_MAGIC)

static inline int object_is_on_stack(const void *obj)
{
    void *stack = task_stack_page(current);

    return (obj >= stack) && (obj < (stack + THREAD_SIZE));
}

extern void thread_stack_cache_init(void);

extern void set_task_stack_end_magic(struct task_struct *tsk);

#endif
